
lib mes = <alpha/mesdialog.ssz>;
lib sdl = <alpha/sdlplugin.ssz>;
lib s = <string.ssz>;
lib se = <alpha/sdlevent.ssz>;
lib cfg = "config.ssz";
lib chr = "char.ssz";
lib com = "common.ssz";
lib sha = "share.ssz";
lib sc = "system-script.ssz";
lib cmd = "command.ssz";
lib fnt = "font.ssz";
lib lua = <alpha/lua.ssz>;
lib al = <alert.ssz>;
lib ld = "loader.ssz";

^^/char code.new(#.chr.chars);

public void error<_t>(^/char m)
{
  .al.alert!_t?(m);
}

void loaderReset()
{
  .com.round = 1;
  .com.p1wins = 0;
  .com.p2wins = 0;
  .com.rexisted[0] = .com.rexisted[1] = 0;
  .ld.reset();
}

void loadStart(&.lua.State L=, int re=)
{
  re = 0;
  .chr.fight = .sc.syst.fig;
  .loaderReset();
  .ld.runTread();
}

void selectStart(&.lua.State L=, int re=)
{
  .sc.syst.selReset();
  .loadStart(L=, re=);
}

void scGame(&.lua.State L=, int re=)
{
  re = 1;
  L.pushNumber((double).match());
}

bool init(&.lua.State L=)
{
  .sc.init(L=);
  L.register("loadStart", .loadStart);
  L.register("selectStart", .selectStart);
  L.register("game", .scGame);
  ret true;
}

int match()
{
  int retval;
  loop{do: retval = .game(); while retval == -2:}
  ret retval;
}
int game()
{
  int winp = 0;
  if(.se.end) ret -1;
  ^^&.chr.Char p.new(#.chr.chars);
  .com.rexisted[0] = .com.rexisted[1] = 0;
  .chr.fight~wi[0].clear();
  .chr.fight~wi[1].clear();
  .com.draws = 0;
  bool load()
  {
    .ld.runTread();
    loop{do:
      if(.ld.state == .ld.State::Complete) break;
      if(.ld.state == .ld.State::Cancel) ret false;
    while .ld.state != .ld.State::Error && .se.event(60):
      if(#.ld.errorMes > 0) .error!.self?(.ld.errorMes);
      ret false;
    }
    ret true;
  }
  int fight(^char ss=, ^&.sha.Share share)
  {
    if(!`load()) ret -1;
    .chr.players.clear();
    .chr.id = .cfg.HelperMax;
    loop{index i = 0; while; do:
      if(#.chr.chars[i] > 0) .chr.chars[i]<>~id = .chr.id++;
      i += 2;
    while i < #.chr.chars:}
    loop{index i = 1; while; do:
      if(#.chr.chars[i] > 0) .chr.chars[i]<>~id = .chr.id++;
      i += 2;
    while i < #.chr.chars:}
    loop{index i = 0; while; do:
      if(#.chr.chars[i] > 0){
        `p[i] = .chr.chars[i]<>;
        .chr.players.add(`p[i]);
        if(.com.rexisted[i&1] == 0){
          `p[i]~loadPallet(.chr.cgi[i].def, `p[i]~palno());
        }
        loop{index j = 0; while; do:
          if(#.chr.chars[j] > 0 && j != i){
            if(#.chr.chars[j]<>~cmd == 0) .chr.chars[j]<>~cmd.new(#.chr.chars);
            .chr.chars[j]<>~cmd[i].copyList(`p[i]~cmd[i]=);
          }
          j++;
        while j < #.chr.chars:}
      }
      i++;
    while i < #`p:}
    if(.com.round == 1){
      .com.p1mw =
        .com.tmode[1] == (int).com.TeamMode::Turns
        ? .com.numturns[1] : .chr.fight~ro.match_wins;
      .com.p2mw =
        .com.tmode[0] == (int).com.TeamMode::Turns
        ? .com.numturns[0] : .chr.fight~ro.match_wins;
      share~copy();
      share~stt = 0;
    }
    .mes.SetSharedString(:ss:);
    bool b = .ld.sszc~run();
    share~push();
    bool w1 = .com.p1wins >= .com.p1mw;
    bool w2 = .com.p2wins >= .com.p2mw;
    `winp = 0;
    if(w1 != w2){
      `winp++;
      if(w2) `winp++;
    }
    .mes.GetSharedString(:ss=:);
    if(.s.equ(ss, "end")) .se.end = true;
    if(.s.equ(ss, "reload")){
      .chr.chars.new(#.chr.chars);
      .loaderReset();
      ret -2;
    }
    ret b && !.s.equ(ss, "esc") ? `winp : -1;
  }
  {
    if(#.cmd.net > 0) .cmd.net~stop();
    ^&.sha.Share share.new(1);
    &.com.SuperDangerousRef sdr;
    sdr.copyRef!&.sha.Share?(share=);
    %char buf .= "gt<>" .= ''sdr.p;
    ^char ss = buf;
    int res = fight(ss=, share);
    if(res < 0) ret res;
    if(
      .com.tmode[0] == (int).com.TeamMode::Turns
      || .com.tmode[1] == (int).com.TeamMode::Turns)
    {
      loop{while; do:
        if(p[0]~sysivar[.chr.iLIFE] <= 0){
          if(.com.tmode[0] == (int).com.TeamMode::Turns){
            .chr.fight~fa[.com.tmode[0]][0].numko++;
            .com.rexisted[0] = 0;
          }
        }
        if(p[1]~sysivar[.chr.iLIFE] <= 0){
          if(.com.tmode[1] == (int).com.TeamMode::Turns){
            .chr.fight~fa[.com.tmode[1]][1].numko++;
            .com.rexisted[1] = 0;
          }
        }
        ss = buf;
        .ld.reset();
        if((res = fight(ss=, share)) < 0) ret res;
      while .com.p1wins < .com.p1mw && .com.p2wins < .com.p2mw && !.se.end:}
    }
  break:
    .cmd.synchronize();
  }
  ret winp;
}

void main()
{//Itumademo Kanseishinai Eienni Mikansei ENgine
  if(!.sdl.init("I.K.E.M.E.N", .cfg.Width, .cfg.Height, .cfg.OpenGL, true)){
    .error!.self?("初期化に失敗");
    ret;
  }
/?/*.cfg.OpenGL:
  if(!.sdl.InitMugenGl(::)){
    .error!.self?("OpenGL の初期設定に失敗");
    ret;
  }
/*?*/
  &.lua.State L;
  if(!.init(L=)) ret;
  if(!L.runFile(.cfg.system)){
    ^/char err = L.toString(-1);
    if(!.s.equ(err[#err-10..-1], "<game end>")) .error!self?(err);
  }
}

main();
.sdl.End(::);
